#include "highgui.h"
#include <iostream>
#include "stdio.h"
#include "cv.h"
#include "math.h"
#include "string.h"
#include <fstream> 
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include "v.h"

using namespace std;

int main(int argc, char* argv[])
{   
  /* put your testing code here */
	
	return 0;
}
/* 
	functions definitions
*/
IplImage* read_image(const char* filename, int iscolor){
     IplImage* img=0;
	 img=cvLoadImage(filename, iscolor);
	 return img;
}

int save_image( const char* filename, const CvArr* image ){
     return cvSaveImage(filename, image);
}

CvCapture* read_video( const char* filename ){
	// return cvCaptureFromFile(filename);
	return cvCaptureFromAVI(filename);
}


IplImage* resize_image(const CvArr* src, int Width, int Height,  int depth,  int channels , int interpolation){
	 IplImage* dst = cvCreateImage( cvSize(Width,Height) , depth, channels);	
	  cvResize(src, dst, interpolation);
	  return dst;
}

IplImage* grabFrameByFrame(CvCapture* capture, int frameID)
{
	cvSetCaptureProperty( capture, CV_CAP_PROP_POS_FRAMES, frameID );
	return cvQueryFrame( capture );
}

IplImage* grabFrameByTime(CvCapture* capture, int timeMSec)
{
	cvSetCaptureProperty( capture, CV_CAP_PROP_POS_MSEC, timeMSec );
	return cvQueryFrame( capture );
}

int getVideoWidth(CvCapture* capture)
{
	return (int)cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH );
}

int getVideoHeight(CvCapture* capture)
{
	return (int)cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT );
}

double getVideoFrameRate(CvCapture* capture)
{
	return cvGetCaptureProperty( capture, CV_CAP_PROP_FPS );
}

double getVideoFrameCount(CvCapture* capture)
{
	return cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_COUNT  );
}

double getVideoLength(CvCapture* capture)
{
	return getVideoFrameCount(capture)/getVideoFrameRate(capture);
}

int fade(CvCapture* capture, CvVideoWriter *writer, int from_time, int to_time, double ratio)
{
	int i,j,k;
	int height;
    int width;
    int step;
	int time = 0;
    int channels;
	int length = getVideoLength(capture) * 1000;
	IplImage* frame;
    uchar * data = 0;
	while(1) {
		
        frame = cvQueryFrame( capture );
		if(!frame)
			break;
		height = frame->height;
		width = frame->width;
        step = frame->widthStep;
		channels = frame->nChannels;
        time = (int) cvGetCaptureProperty( capture, CV_CAP_PROP_POS_MSEC );
		if(time >= 0 && time <= from_time){
			//TODO: 
			cvWriteFrame(writer,frame);   

		}
		else if (time > from_time && time <= to_time){
			//TODO:
			data  = (uchar *)frame->imageData;
			for(i=0;i<height;i++){ 
				for(j=0;j<width;j++){
					
						for(k=0;k<channels;k++){
						 int temp = data[i*step+j*channels+k];
				         temp = temp * ratio;
					     data[i*step+j*channels+k] = (temp > 255) ? 255 : temp;
					    
						}
			  }
		   }

            ratio = ratio *1.1;
			cvWriteFrame(writer,frame);   

		}
		else if (time > to_time && time <= length){
			//TODO:
			cvWriteFrame(writer,frame);   
		}
		else{
			printf("fadeOut Error! \n");
			return 0;
		}
		
	}

}

CvCapture* join(CvCapture* capture1, CvCapture* capture2, const char* filename)
{
	IplImage* frame1, *frame2;	
	CvVideoWriter *writer = 0;
	int frameW = getVideoWidth(capture1);
	int frameH = getVideoHeight(capture1);
	double fps = getVideoFrameRate(capture1);
	int isColor = 1;
    writer=cvCreateVideoWriter(filename,CV_FOURCC('I','Y','U','V'),
                      fps,cvSize(frameW,frameH),isColor);
	
	 while(1) {
		frame1 = cvQueryFrame( capture1 );
		 if(!frame1)
		  break;
		  
		cvWriteFrame(writer,frame1);        
       
	 }
	 while(1) {
		frame2 = cvQueryFrame( capture2);
		 if(!frame2)
		  break;
		
		cvWriteFrame(writer,frame2);        
      
	 }
	cvReleaseCapture( &capture1 );
    cvReleaseCapture( &capture2 );
	cvReleaseVideoWriter(&writer);

	return read_video(filename);

}

CvCapture* resize_video(CvCapture* video, int Width, int Height, const char* filename)
{
	IplImage* frame;	
	IplImage* dst;
	CvVideoWriter *writer = 0;
	int frameW = Width;
	int frameH = Height;
	double fps = getVideoFrameRate(video);
	int isColor = 1;
	
    writer=cvCreateVideoWriter(filename,CV_FOURCC('I','Y','U','V'),
                      fps,cvSize(frameW,frameH),isColor);
	
	 while(1) {
		frame = cvQueryFrame( video );
		 if(!frame)
		  break;
	    dst = resize_image(frame, Width, Height, frame->depth, frame->nChannels);
		cvWriteFrame(writer,dst);        
       
	 }
	 
    cvReleaseCapture( &video);
	cvReleaseVideoWriter(&writer);

	return read_video(filename);
}

CvCapture* cropVideo(CvCapture* video, int x, int y, int Width, int Height, const char* filename)
{
	IplImage* frame;	
	CvVideoWriter *writer = 0;
	int frameW = Width;
	int frameH = Height;
	double fps = getVideoFrameRate(video);
	int isColor = 1;
	
    writer=cvCreateVideoWriter(filename,CV_FOURCC('I','Y','U','V'),
                      fps,cvSize(frameW,frameH),isColor);

	 while(1) {
		frame = cvQueryFrame( video );
		 if(!frame)
		  break;

	 cvSetImageROI(frame,cvRect(x, y, Width, Height));
     IplImage* dst = cvCreateImage(cvSize(Width,Height), frame->depth, frame->nChannels);
     cvCopy(frame, dst); 
     cvWriteFrame(writer,dst);        
       
	 }

	 cvReleaseCapture( &video);
	 cvReleaseVideoWriter(&writer);
	 return read_video(filename);

}

CvCapture* zoom(CvCapture* video, float w_rate, float h_rate , const char* filename)
{
	IplImage* frame;	
	CvVideoWriter *writer = 0;
	int frameW = getVideoWidth(video);
	int frameH = getVideoHeight(video);
	double fps = getVideoFrameRate(video);
	int isColor = 1;
	
    writer=cvCreateVideoWriter(filename,CV_FOURCC('I','Y','U','V'),
                      fps,cvSize(frameW,frameH),isColor);

	 while(1) {
		frame = cvQueryFrame( video );
		 if(!frame)
		  break;

	 IplImage* img = resize_image(frame, (int)(frameW*w_rate), (int)(frameH*h_rate),  frame->depth, frame->nChannels);
	 int x = abs((img->width-frameW)/2);
	 int y = abs((img->height-frameH)/2);
	 cvSetImageROI(img,cvRect(x, y, frameW, frameH));
     IplImage* dst = cvCreateImage(cvSize(frameW,frameH), img->depth, img->nChannels);
     cvCopy(img, dst); 
     cvWriteFrame(writer,dst);        
       
	 }
     
	 cvReleaseCapture( &video);
	 cvReleaseVideoWriter(&writer);
	 return read_video(filename);

}

CvCapture* img2video(IplImage* img, float duration,  const char* filename)
{
	IplImage* frame = img;	
	CvVideoWriter *writer = 0;
	int frameW = frame->width;
	int frameH = frame->height;
	double fps = 10;
	int isColor = 1;
	int count=0;
	
    writer=cvCreateVideoWriter(filename,CV_FOURCC('I','Y','U','V'),
                      fps,cvSize(frameW,frameH),isColor);

	 while(1) {
	 if(count == (int) (fps * duration) )
		 break;

     cvWriteFrame(writer,frame);        

	 count ++;
       
	 }
     
	 cvReleaseImage( &frame);
	 cvReleaseVideoWriter(&writer);
	 return read_video(filename);
}

int* grabPixel(IplImage* img,  int x, int y)
{
	  int k;
      int height = img->height;
      int width = img->width;
      int step = img->widthStep;
      int channels = img->nChannels;
	  int *pixel = (int*)malloc(sizeof(int)*channels);
      uchar * data = (uchar *)img->imageData;
     
			for(k=0;k<channels;k++)
                  pixel[k]=data[y*step+x*channels+k];

	  return pixel;
}

CvCapture* cut(CvCapture* video, float t1,  float t2, const char* filename)
{
	IplImage* frame;
	double fps = getVideoFrameRate(video);
	int frameW = getVideoWidth(video);
	int frameH = getVideoHeight(video);
	int isColor = 1;
	int start_frame = fps*t1;
	int end_frame = fps*t2;

	cvSetCaptureProperty( video, CV_CAP_PROP_POS_FRAMES, start_frame );	
	
	CvVideoWriter *writer = 0;
	writer=cvCreateVideoWriter(filename,CV_FOURCC('I','Y','U','V'),
                      fps,cvSize(frameW,frameH),isColor);
	
	
	 while(1) {
		frame = cvQueryFrame( video );
		if(end_frame == (int)cvGetCaptureProperty( video, CV_CAP_PROP_POS_FRAMES) || !frame)
		  break;
		  
		cvWriteFrame(writer,frame);        
	 	 
	 }
	cvReleaseCapture( &video );
	cvReleaseVideoWriter(&writer);
	return read_video(filename);
}